package com.edge.pbx.view;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageButton;

import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.edge.pbxdsp.R;
import com.hanlink.dsp.ui.view.CenterTextButton;
import com.qztech.utils.YzDebug;

import static com.edge.pbx.view.summing.PbxOutputSelectChannelsLayout.sColorNormal;
import static com.edge.pbx.view.summing.PbxOutputSelectChannelsLayout.sColorSelected;

/**
 * Copyright (C), 深圳市东乘电子科技有限公司
 * Carate By YangZhong
 */
public class PbxCircleSeekBar extends ViewGroup implements View.OnClickListener {
    private Paint mPaint;
    private RectF mRectF; //进度条圆圈的绘制区域
    private int mLineWidth = 8;//进度条的绘制宽度
    private int mThumbCircleRadius;//滑块的绘制半径
    private int mProgressRaduis;//进度条圆圈的半径，用于计算滑块的位置
    private int mCenterX, mCenterY;//中心点

    private final float mStartDegress = 135f;//进度条绘制的起始弧度
    private float mStepDegress = 1;//进度条弧度步进

    private final float mMaxDegress = 270f;//进度条最大绘制弧度
    private int mMaxProgress = 100;//最大进度
    private float mCurDegress;//当前进度的弧度
    private int mCurProgress;//当前进度
    private int mMinProgress = 0;
    private float mMinDegress = 0;
    private Path mClipPath;
    private int mSubAddSize;
    protected Drawable mDrawableTitle;
    private TextPaint mTextPaint;
    private int mTextY;
    private final int BASE_VIEW_SIZE = 360;
    private final int BASE_ADD_SUB_SIZE = 58;
    private int mIndex = 0;
    private float mTitleMarginTop = 0.280f;
    private float mTextMarginTop = 0.62f;
    private int mMaxRadius = 1;

    protected CenterTextButton mBtnTitle;
    private ImageButton mIbAdd, mIbSub;

    public PbxCircleSeekBar(Context context) {
        super(context);
        init(context, null);
    }


    public PbxCircleSeekBar(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    private void init(Context context, AttributeSet attrs) {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeCap(Paint.Cap.ROUND);

        mRectF = new RectF();
        mClipPath = new Path();
        mTextPaint = new TextPaint();
        mTextPaint.setColor(Color.WHITE);
        mTextPaint.setFakeBoldText(true);
        if (attrs != null) {
            TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.PbxCircleSeekBar);
            mDrawableTitle = array.getDrawable(R.styleable.PbxCircleSeekBar_pbx_pcsb_title_bg);
            mMaxProgress = array.getInteger(R.styleable.PbxCircleSeekBar_pbx_pcsb_max, mMaxProgress);
            mMinProgress = array.getInteger(R.styleable.PbxCircleSeekBar_pbx_pcsb_min, mMinProgress);
            mIndex = array.getInt(R.styleable.PbxCircleSeekBar_pbx_pcsb_index, mIndex);
            mTitleMarginTop = array.getFloat(R.styleable.PbxCircleSeekBar_pbx_pcsb_title_marginTop, mTitleMarginTop);
            mTextMarginTop = array.getFloat(R.styleable.PbxCircleSeekBar_pbx_pcsb_text_margintTop, mTextMarginTop);

            if (array.getBoolean(R.styleable.PbxCircleSeekBar_pbx_pcsb_title_is_btn, false)) {
                mBtnTitle = new CenterTextButton(context);
                int id = array.getResourceId(R.styleable.PbxCircleSeekBar_pbx_pcsb_title_bg, 0);
//                mBtnTitle.setBackground(mDrawableTitle);
//                mBtnTitle.setBackgroundColor(Color.RED);
                mBtnTitle.setId(R.id.pbx_circleseekbar_title_btn);
                mBtnTitle.setBackgroundResource(id);
//                mBtnTitle.setBackgroundColor(Color.RED);
                mBtnTitle.setTextColor(context.getColorStateList(R.color.btn_text_white));
                mBtnTitle.setGravity(Gravity.CENTER);
                mBtnTitle.setOnClickListener(this);
                addView(mBtnTitle);
            }

            array.recycle();
            if (mCurProgress < mMinProgress) {
                mCurProgress = mMinProgress;
            }
        }
        mStepDegress = mMaxDegress / mMaxProgress;
        mMinDegress = mMinProgress * mStepDegress;
        YzDebug.d("Yang", "mMaxProgress:" + mMaxProgress + " mMinProgress:" + mMinProgress + " mCurProgress:" + mCurProgress);

        mIbAdd = new ImageButton(context);
        mIbSub = new ImageButton(context);

        mIbAdd.setBackgroundResource(R.drawable.pbx_common_btn_add);
//        mIbAdd.setBackgroundColor(Color.GREEN);
        mIbAdd.setImageDrawable(null);
        mIbSub.setBackgroundResource(R.drawable.pbx_common_btn_sub);
        mIbSub.setImageDrawable(null);

        mIbAdd.setOnClickListener(this);
        mIbSub.setOnClickListener(this);
        mIbAdd.setId(R.id.pbx_circleseekbar_add_btn);
        mIbSub.setId(R.id.pbx_circleseekbar_sub_btn);

        addView(mIbAdd);
        addView(mIbSub);
    }

    public int getIndex() {
        return mIndex;
    }

    public void setMax(int max) {
        this.mMaxProgress = max;
        this.mStepDegress = mMaxDegress / mMaxProgress;
        this.mMinDegress = mStepDegress * mMinProgress;
        postInvalidate();
    }

    public void setMin(int min) {
        this.mMinProgress = min;
        mMinDegress = min * mStepDegress;
        if (mCurProgress < min) {
            setProgress(min);
        } else {
            postInvalidate();
        }
    }

    public int getProgress() {
        return mCurProgress;
    }

    private ValueAnimator mValueAnimator;

    public void setProgressForce(int progress) {
        mCurProgress = mMinProgress;
        mCurDegress = mMinDegress;
        setProgress(progress, true);
    }

    public void setProgress(int progress, boolean anim) {
        if (progress < mMinProgress) return;
        if (mCurProgress == progress) return;
        if (Math.abs(mCurProgress - progress) < 2) {
            anim = false;
        }
        this.mCurProgress = progress;
        cancelAnimator();
        if (anim) {
            float tagDegress = progress * mStepDegress;
            mValueAnimator = ValueAnimator.ofFloat(mCurDegress, tagDegress);
            final ValueAnimatorListener listener = new ValueAnimatorListener();
            mValueAnimator.addListener(listener);
            mValueAnimator.addUpdateListener(listener);
            mValueAnimator.setDuration(500);
            mValueAnimator.start();
        } else {
            this.mCurDegress = mCurProgress * mStepDegress;
            postInvalidate();

        }
    }

    public void setProgress(int progress) {
        setProgress(progress, false);
    }

    protected int mCircleBgSize = 0;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        mCenterX = width >> 1;
        mCenterY = (int) (height * 0.48f);
        final int size = Math.min(width, height);
        mMaxRadius = size >> 1;
        mMaxRadius = mMaxRadius * mMaxRadius;
        mTextPaint.setTextSize(size * 0.15f);
        mSubAddSize = BASE_ADD_SUB_SIZE * size / BASE_VIEW_SIZE;
        mLineWidth = (int) (6f * mSubAddSize / BASE_ADD_SUB_SIZE);
        mThumbCircleRadius = mLineWidth * 3;
        //半径需要减去滑块的半径以及滑块的绘制半径
        int r1 = size / 2 - mThumbCircleRadius - mLineWidth;
        int r2 = (size - mSubAddSize) / 2;
        mProgressRaduis = Math.min(r1, r2);

        mCircleBgSize = mProgressRaduis * 2;
        mTextY = (int) (size * mTextMarginTop);
        mPaint.setStrokeWidth(mLineWidth);


        int w = (int) (mCircleBgSize * 0.75f);
        int h = mDrawableTitle.getMinimumHeight() * w / mDrawableTitle.getMinimumWidth();
        if (mBtnTitle != null) {
            mBtnTitle.measure(MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
        }

    }

//
//    private boolean isEnable = true;
//    @Override
//    public void setEnabled(boolean enabled) {
//        isEnable = enabled;
//    }
//
//    @Override
//    public boolean isEnabled() {
//        return true;
//    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
//        super.onLayout(changed, left, top, right, bottom);
        final int width = right - left;
        final int height = bottom - top;

//        Log.d("Yang", " onLayout----------:" + width + "  " + height);

        int baseL = (width - mCircleBgSize) / 2;
        //以背景圆的直径为参考， 保持形状不变

        if (mDrawableTitle != null) {
            int baseTop = (height - mCircleBgSize) / 2;
            int w = (int) (mCircleBgSize * 0.75f);
            int l = baseL + (mCircleBgSize - w) / 2;
            int h = mDrawableTitle.getMinimumHeight() * w / mDrawableTitle.getMinimumWidth();
            top = baseTop + (int) (mCircleBgSize * mTitleMarginTop) - h / 2;

            mDrawableTitle.setBounds(l, top, l + w, top + h);
            if (mBtnTitle != null) {
                mBtnTitle.layout(l, top, l + mBtnTitle.getMeasuredWidth(),
                        top + mBtnTitle.getMeasuredHeight());
//                YzDebug.d("onLayout mBtnTitle:" +
//                        l + " " + top + " " + mBtnTitle.getMeasuredWidth() + "  " + mBtnTitle.getMeasuredHeight());
            }


        }

        layoutSubAdd(mIbAdd, mMaxDegress + 5);
        layoutSubAdd(mIbSub, -5);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            int x = (int) (event.getX() - mCenterX);
            int y = (int) (event.getY() - mCenterY);
            if (x * x + y * y > mMaxRadius) {
                YzDebug.d("onTouchEvent   >  mMaxRadius return");
                return false;
            }
            if(x *x + y * y < mMaxRadius/2){
                return false;
            }
        }
        if (!isEnabled()){
            YzDebug.d("onTouchEvent   >  enable false return");
            return false;
        }
        calTouchProgress(event.getX(), event.getY(), event.getAction());
        return true;

    }

    private void calTouchProgress(float touchX, float touchY, int action) {
        cancelAnimator();
        int x = (int) (touchX - mCenterX);
        int y = (int) (mCenterY - touchY);
        //以Y轴为分割，从3点到9点方向，上面为180~0，下面为-180~0,加上180以后，9点逆时针方向到9点为0~360度

        double degress = 180d + Math.toDegrees(Math.atan2(y, x));
        //最下面的90弧度去掉
        if (degress > 45 && degress < 90) {
            degress = 45;
        } else if (degress >= 90 && degress < 135) {
            degress = 135;
        }
        if (degress <= 45) {
            degress += 360d;
        }
        degress = 405 - degress;
        if (degress < mMinDegress) {
            degress = mMinDegress;
        }
        ;
        if (mCurDegress != degress) {
            mCurDegress = (float) degress;
            postInvalidate();
            int progress = (int) ((mCurDegress + mStepDegress / 2) / mStepDegress);
            if (mCurProgress != progress) {
                mCurProgress = progress;
                if (mOnCircleSeekBarListener != null) {
                    mOnCircleSeekBarListener.onProgressChange(this, progress, action);
                }
                return;
            }
        }
        if (action == MotionEvent.ACTION_UP) {
            if (mOnCircleSeekBarListener != null) {
                mOnCircleSeekBarListener.onProgressChange(this, mCurProgress, action);
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);

        drawSelf(canvas);
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void drawSelf(Canvas canvas) {
        if (mCurDegress < mMinDegress)
            mCurDegress = mMinDegress;
        double thumbDegress = Math.toRadians(mCurDegress + 45);
        int thumbCenterX = mCenterX - (int) (Math.sin(thumbDegress) * mProgressRaduis);
        int thumbCenterY = mCenterY + (int) (Math.cos(thumbDegress) * mProgressRaduis);

        if (mBtnTitle == null && mDrawableTitle != null) {
            mDrawableTitle.draw(canvas);
        }
        canvas.save();
        mClipPath.reset();
        mClipPath.addCircle(thumbCenterX, thumbCenterY, mThumbCircleRadius, Path.Direction.CW);
        canvas.clipOutPath(mClipPath);

        mPaint.setColor(sColorNormal);
        mRectF.set(mCenterX - mProgressRaduis, mCenterY - mProgressRaduis, mCenterX + mProgressRaduis, mCenterY + mProgressRaduis);
        //绘制进度条背景
        canvas.drawArc(mRectF, mStartDegress, mMaxDegress, false, mPaint);


        mPaint.setColor(sColorSelected);
        //绘制进度条

        canvas.drawArc(mRectF, mStartDegress, mCurDegress, false, mPaint);
        canvas.restore();
        //绘制滑块
        canvas.drawCircle(thumbCenterX, thumbCenterY, mThumbCircleRadius, mPaint);

        //绘制文字
        if (mOnCircleSeekBarTextListener != null) {
            String text = mOnCircleSeekBarTextListener.onValueToText(mCurProgress);
            canvas.drawText(text, mCenterX - mTextPaint.measureText(text) / 2, mTextY, mTextPaint);
        }

    }

    private void layoutSubAdd(ImageButton btn, float degress) {
        double thumbDegress = Math.toRadians(degress + 45);
        int x = mCenterX - (int) (Math.sin(thumbDegress) * (mProgressRaduis + mSubAddSize * 2));

        int y = mCenterY + (int) (Math.cos(thumbDegress) * mProgressRaduis);
        int left = 0;
        if (btn == mIbSub) {
            left = x;
            btn.layout(0, y, left + mSubAddSize, y + mSubAddSize + x);
        } else {
            left = x - mSubAddSize;
            btn.layout(left, y, getWidth(), y + mSubAddSize + (getWidth() - x));
        }


    }

    private void cancelAnimator() {
        if (mValueAnimator != null)
            mValueAnimator.cancel();
        mValueAnimator = null;
    }

    @Override
    public void onClick(View v) {
        YzDebug.d("onClick :"+(mOnCircleSeekBarFunListener == null) +
                " enable:"+ isEnabled());
        if (mOnCircleSeekBarFunListener == null) return;
        switch (v.getId()) {
            case R.id.pbx_circleseekbar_title_btn:
                mOnCircleSeekBarFunListener.onFunClick(this,FunId.FUN_ID_TITLE);
                break;
            case R.id.pbx_circleseekbar_add_btn:
                mOnCircleSeekBarFunListener.onFunClick(this,FunId.FUN_ID_ADD);
                break;
            case R.id.pbx_circleseekbar_sub_btn:
                mOnCircleSeekBarFunListener.onFunClick(this,FunId.FUN_ID_SUB);
                break;
        }
    }

    private final class ValueAnimatorListener implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
        @Override
        public void onAnimationStart(Animator animation) {
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            mValueAnimator = null;
            mCurDegress = mCurProgress * mStepDegress;
            postInvalidate();
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            mValueAnimator = null;
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
        }

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            Float value = (Float) animation.getAnimatedValue();
            mCurDegress = value;
            postInvalidate();
        }
    }

    private OnCircleSeekBarListener mOnCircleSeekBarListener;

    public void setOnCircleSeekBarListener(OnCircleSeekBarListener onCircleSeekBarListener) {
        mOnCircleSeekBarListener = onCircleSeekBarListener;
    }

    public interface OnCircleSeekBarListener {
        void onProgressChange(PbxCircleSeekBar seekBar, int progress, int action);
    }

    private OnCircleSeekBarTextListener mOnCircleSeekBarTextListener;

    public void setOnCircleSeekBarTextListener(OnCircleSeekBarTextListener onCircleSeekBarTextListener) {
        mOnCircleSeekBarTextListener = onCircleSeekBarTextListener;
    }

    public interface OnCircleSeekBarTextListener {
        String onValueToText(int value);
    }

    public enum FunId {
        FUN_ID_TITLE, FUN_ID_SUB, FUN_ID_ADD
    }

    private OnCircleSeekBarFunListener mOnCircleSeekBarFunListener;

    public void setOnCircleSeekBarFunListener(OnCircleSeekBarFunListener onCircleSeekBarFunListener) {
        mOnCircleSeekBarFunListener = onCircleSeekBarFunListener;
    }

    public interface OnCircleSeekBarFunListener {
        void onFunClick(PbxCircleSeekBar bar, FunId id);
    }


}
